package edu.ccut.saturn.studio.naviagtor;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.core.JarEntryFile;
import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
import org.eclipse.jdt.internal.core.PackageFragment;
import org.eclipse.jdt.internal.ui.navigator.JavaNavigatorLabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.navigator.CommonViewer;
import org.eclipse.ui.progress.UIJob;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import edu.ccut.saturn.studio.component.model.ComponentModel;
import edu.ccut.saturn.studio.core.util.xml.SaturnW3CUtil;
import edu.ccut.saturn.studio.saturndata.model.SaturnDataModel;
import edu.ccut.saturn.studio.saturndata.model.ValidateModel;

public class SaturnLabelProvider extends JavaNavigatorLabelProvider implements
		IResourceChangeListener, IResourceDeltaVisitor {

	private final static String SATURN_FILE_NAME = ".saturn";

	private static final String CN_EDU_CCUT_SATURNCONTENT_VIEW = "cn.edu.ccut.saturncontent.view";

	private boolean isFileName = true;

	private static SaturnLabelProvider instance = null;

	private CommonViewer commonViewer;
	private static final String FILE_SUFFIX = "action";
	private static final String FILE_SUFFIX1 = "logic";
	private static final String FILE_SUFFIX2 = "component";

	public static CommonViewer getProjectExplorerView() {
		CommonNavigator navigator = getProjectExplorerNavigator();
		if (navigator != null) {
			return navigator.getCommonViewer();
		}
		return null;
	}

	public static CommonNavigator getProjectExplorerNavigator() {
		IViewPart part = null;
		try {
			IWorkbenchWindow window = PlatformUI.getWorkbench()
					.getActiveWorkbenchWindow();

			if (window != null) {
				part = window.getActivePage().showView(
						CN_EDU_CCUT_SATURNCONTENT_VIEW, null,
						IWorkbenchPage.VIEW_VISIBLE);

				if (part != null && part instanceof CommonNavigator) {
					return (CommonNavigator) part;
				}
			}
		} catch (PartInitException e) {
			e.printStackTrace();
		}

		return null;
	}

	public static SaturnLabelProvider getInstance() {
		return instance;
	}

	public void changeName() {
		isFileName = !isFileName;
	}

	public SaturnLabelProvider() {
		instance = this;
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this,
				IResourceChangeEvent.POST_CHANGE);
	}

	@Override
	public String getText(Object element) {

		String name = this.getName(element);

		if ("".equals(name)) {
			return super.getText(element);
		} else if (element instanceof PackageFragment) {
			return name;
		} else if (element instanceof IProject) {
			return name;	
		} else {
			return getTextWithOutSuffix(name);
		}

	}

	private String getName(Object element) {
		if (isFileName) {
			if (element instanceof IFile) {
				IFile file = (IFile) element;
				return file.getName();
			}

			if (element instanceof JarEntryFile) {
				JarEntryFile file = (JarEntryFile) element;
				return file.getName();
			}
		} else {
			String fileNameInXML = "";

			if (element instanceof IFile) {
				IFile file = (IFile) element;
				if (isSupportXMLFileName(file.getName())) {
					fileNameInXML = getFileName(file);
					if (!"".equals(fileNameInXML)) {
						return fileNameInXML;
					}
				}
			}

			if (element instanceof JarEntryFile) {
				JarEntryFile file = (JarEntryFile) element;

				if (isSupportXMLFileName(file.getName())) {
					fileNameInXML = getFileName(file);
					if (!"".equals(fileNameInXML)) {
						return fileNameInXML;
					}
				}
			}

			// 处理文件夹
			if (element instanceof PackageFragment) {
				IResource resource = ((PackageFragment) element).getResource();
				if (resource instanceof IFolder) {
					IFile file = ((IFolder) resource).getFile(SATURN_FILE_NAME);

					SaturnDirectory saturnDirectory = SaturnDirectory
							.loadSaturnDirectory(file);

					if (saturnDirectory != null
							&& !"".equals(saturnDirectory.getName())) {
						return saturnDirectory.getName();
					}
				}

				// //////////////
				// 处理jar中的包
				IPackageFragmentRoot ip = ((PackageFragment) element)
						.getPackageFragmentRoot();
				if (ip instanceof JarPackageFragmentRoot) {
					SaturnDirectory saturnDirectory = getSaturnDirectoryFromJar(((PackageFragment) element));

					if (saturnDirectory != null
							&& !"".equals(saturnDirectory.getName())) {
						return saturnDirectory.getName();
					}
				}
			}
		}

		return super.getText(element);
	}

	private boolean isSupportXMLFileName(String fileName) {
		return fileName.endsWith(SaturnFile.LOGIC_FILE_SUFFIX)
				|| fileName.contains(SaturnFile.ACTION_FILE_SUFFIX)
				|| fileName.contains(SaturnFile.WORKFLOW_FILE_SUFFIX)
				|| fileName.contains(SaturnFile.SATURN_DATA_FILE_SUFFIX)
				|| fileName.contains(SaturnFile.VALIDATE_FILE_SUFFIX)
				|| fileName.contains(SaturnFile.COMPONENT_FILE_SUFFIX);
	}

	@Override
	public Image getImage(Object element) {
		String saturnType = "";
		if (element instanceof PackageFragment) {
			IResource iResource = ((PackageFragment) element).getResource();
			if (iResource instanceof IFolder) {
				IFolder iFolder = (IFolder) iResource;
				IFile ifile = iFolder.getFile(SATURN_FILE_NAME);
				SaturnDirectory saturnDirectory = SaturnDirectory
						.loadSaturnDirectory(ifile);
				if (saturnDirectory != null) {
					saturnType = saturnDirectory.getType();
					return SaturnFile.getImageFromDiretoryType(saturnType);
				}
			}

			// 处理jar中的包
			IPackageFragmentRoot ip = ((PackageFragment) element)
					.getPackageFragmentRoot();
			if (ip instanceof JarPackageFragmentRoot) {
				SaturnDirectory saturnDirectory = getSaturnDirectoryFromJar(((PackageFragment) element));

				if (saturnDirectory != null
						&& !"".equals(saturnDirectory.getType())) {
					return SaturnFile.getImageFromDiretoryType(saturnDirectory
							.getType());
				}
			}
		}
		return super.getImage(element);
	}

	public SaturnDirectory getSaturnDirectoryFromJar(
			PackageFragment packageFragment) {

		String fname = packageFragment.getElementName().replace(".", "/");
		IPackageFragmentRoot ip = ((PackageFragment) packageFragment)
				.getPackageFragmentRoot();
		JarPackageFragmentRoot jar = (JarPackageFragmentRoot) ip;

		ZipFile zipFile = null;
		InputStream inputStream = null;
		try {
			zipFile = jar.getJar();

			if (zipFile != null && zipFile.getEntry(fname + "/.saturn") != null) {
				ZipEntry zipEntry = zipFile.getEntry(fname + "/.saturn");
				byte[] contents = Util
						.getZipEntryByteContent(zipEntry, zipFile);

				inputStream = (InputStream) new ByteArrayInputStream(contents);
				return SaturnDirectory.loadSaturnDirectory(inputStream);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return null;
	}

	/**
	 * 监听资源变化。
	 * 
	 * @author alf 2008-9-1
	 */
	public void resourceChanged(IResourceChangeEvent event) {
		try {
			IResourceDelta delta = event.getDelta();
			delta.accept(this);
		} catch (CoreException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 处理资源变化。
	 * 
	 * @author alf 2008-9-1
	 */
	public boolean visit(IResourceDelta delta) throws CoreException {
		IResource source = delta.getResource();
		switch (source.getType()) {
		case IResource.ROOT:
		case IResource.PROJECT:
		case IResource.FOLDER:
			return true;
		case IResource.FILE:
			final IFile file = (IFile) source;
			if (FILE_SUFFIX.equals(file.getFileExtension())
					|| FILE_SUFFIX1.equals(file.getFileExtension())
					|| FILE_SUFFIX2.equals(file.getFileExtension())) {
				commonViewer = getProjectExplorerView();
				new UIJob("Update Files...") {
					public IStatus runInUIThread(IProgressMonitor monitor) {
						if (commonViewer != null
								&& !commonViewer.getControl().isDisposed())
							commonViewer.refresh(file);
						return Status.OK_STATUS;
					}
				}.schedule();
			}
			return false;
		}
		return false;
	}

	public static String getTextWithOutSuffix(String name) {
		if (!SaturnFile.isSaturnFile(name)) {
			return name;
		}

		int i = name.lastIndexOf(".");

		if (i > 0 && i < name.length() - 1) {
			return name.substring(0, i);
		}

		return name;
	}

	private String getFileName(IFile ifile) {
		InputStream inputStream = null;
		try {
			if (ifile.exists()) {
				inputStream = ifile.getContents();

				String xmlName = getFileName(inputStream, ifile.getName());
				if (!xmlName.equals("")) {
					return xmlName;
				}
			}
		} catch (CoreException e) {
			e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return "";
	}

	private String getFileName(JarEntryFile file) {
		InputStream inputStream = null;
		try {
			inputStream = file.getContents();

			String xmlName = getFileName(inputStream, file.getName());
			if (!xmlName.equals("")) {
				return xmlName;
			}
		} catch (CoreException e) {
			e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return "";
	}

	public String getFileName(InputStream inputStream, String fileName) {
		String name = "";
		try {
			Document document = SaturnW3CUtil.getDocument(inputStream);
			Element root = document.getDocumentElement();

			if (fileName.endsWith(SaturnFile.COMPONENT_FILE_SUFFIX)) {
				ComponentModel componentModel = new ComponentModel(document);
				name = componentModel.getComponent().getName();
			} else if (fileName.endsWith(SaturnFile.VALIDATE_FILE_SUFFIX)) {
				ValidateModel validateModel = new ValidateModel(document);
				name = validateModel.getValidateVO().getName();
			} else if (fileName.endsWith(SaturnFile.SATURN_DATA_FILE_SUFFIX)) {
				SaturnDataModel saturnDataModel = new SaturnDataModel(document);
				name = saturnDataModel.getSaturnData().getType();
			} else if (fileName.endsWith(SaturnFile.ACTION_FILE_SUFFIX)
					|| fileName.endsWith(SaturnFile.LOGIC_FILE_SUFFIX)
					|| fileName.endsWith(SaturnFile.WORKFLOW_FILE_SUFFIX)) {

				Node informationNode = SaturnW3CUtil.getFirstChildByName(root,
						"information");
				name = SaturnW3CUtil.getChildNodeValue(informationNode, "name");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return name;
	}
}
